package com.fm.financemanage.component;

import com.alibaba.fastjson.JSONObject;
import org.springframework.data.redis.core.RedisConnectionUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author : tony
 * @Date: 2019-04-29 20:42
 * @Description:
 */
@SuppressWarnings("all")
@Component
public class RedisComponent {

    /**
     * 默认使用的 redis
     */
    @Resource(name = "defaultRedisTemplate")
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * redis 中存放值
     **/
    public void setValue(String key, Object value) {
        try {

            redisTemplate.opsForValue().set(key, value);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            RedisConnectionUtils.unbindConnection(Objects.requireNonNull(redisTemplate.getConnectionFactory()));
        }
    }


    /**
     * 从 redis 中获取数据
     **/
    public Object getValue(String key) {
        try {
            return redisTemplate.opsForValue().get(key);
        } catch (Exception e) {
            return null;
        } finally {
            RedisConnectionUtils.unbindConnection(Objects.requireNonNull(redisTemplate.getConnectionFactory()));
        }
    }

    /**
     * 像 redis 的 hash 中存放对应的数据
     **/
    public boolean putHash(String setName, String key, Object value) {
        try {
            redisTemplate.opsForHash().put(setName, key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            RedisConnectionUtils.unbindConnection(Objects.requireNonNull(redisTemplate.getConnectionFactory()));
        }
        return true;
    }

    /**
     * 从redis的hash中获取对应的数据
     **/
    public Object getHashByKey(String setName, String key) {
        try {


            return redisTemplate.opsForHash().get(setName, key);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            RedisConnectionUtils.unbindConnection(Objects.requireNonNull(redisTemplate.getConnectionFactory()));
        }
        return null;
    }



    //设置hash中某个值的过期时间
    public Object setHashExipre(String setName, String key, String value, long time) {
        try {
            redisTemplate.opsForHash().put(setName, key, value);
            return redisTemplate.expire(setName, time, TimeUnit.DAYS);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            RedisConnectionUtils.unbindConnection(Objects.requireNonNull(redisTemplate.getConnectionFactory()));
        }
        return null;
    }

    //设置hash中的值
    public void setHash(String setName, String key, String value) {
        try {
            redisTemplate.opsForHash().put(setName, key, value);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            RedisConnectionUtils.unbindConnection(Objects.requireNonNull(redisTemplate.getConnectionFactory()));
        }
    }

    /**
     * 哈希字段累加1
     *
     * @param redisKey redis key
     * @param hashKey  hash中的key
     */
    public Long incrementHash(String redisKey, String hashKey, Integer type) {
        try {
            return redisTemplate.opsForHash().increment(redisKey, hashKey, type == 1 ? 1 : -1);
        } catch (Exception e) {
            RedisConnectionUtils.unbindConnection(Objects.requireNonNull(redisTemplate.getConnectionFactory()));
            e.printStackTrace();
        }
        return 0L;
    }

    //获取hash所有元素
    public Map<Object, Object> getHashAllEle(String setName) {
        try {
            return redisTemplate.opsForHash().entries(setName);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            RedisConnectionUtils.unbindConnection(Objects.requireNonNull(redisTemplate.getConnectionFactory()));
        }
        return null;
    }

    //删除hash中某个元素
    public boolean delectHashByKey(String setName, String key) {
        try {
            redisTemplate.opsForHash().delete(setName, key);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            RedisConnectionUtils.unbindConnection(Objects.requireNonNull(redisTemplate.getConnectionFactory()));
        }
        return false;
    }


    /**
     * 普通缓存放入并设置时间
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒) time要大于0 如果time小于等于0 将设置无限期
     * @return true成功 false 失败
     */
    public boolean setExTimeValue(String key, Object value, long time) {
        try {
            if (time > 0) {
                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            } else {
                setValue(key, value);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            RedisConnectionUtils.unbindConnection(Objects.requireNonNull(redisTemplate.getConnectionFactory()));
        }
        return false;
    }

    //获取某个key的过期时间
    public long getExTimeByKey(String key) {
        try {
            return redisTemplate.opsForValue().getOperations().getExpire(key);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            RedisConnectionUtils.unbindConnection(Objects.requireNonNull(redisTemplate.getConnectionFactory()));
        }
        return 0;
    }

    /**
     * @param key redis key的名称
     * @param o   值
     * @return long
     * @author zpc
     * @date 11:35 2021/8/31
     **/
    public long addSetEle(String key, Object o) {
        try {
            SetOperations<String, Object> stringObjectSetOperations = redisTemplate.opsForSet();
            Long add = stringObjectSetOperations.add(key, o);
            return add == null ? 0 : add;
        } catch (Exception e) {

            e.printStackTrace();
        } finally {
            RedisConnectionUtils.unbindConnection(Objects.requireNonNull(redisTemplate.getConnectionFactory()));
        }
        return 0;
    }

    //获取set的长度
    public long getSizeSetByKey(String key) {
        try {

            return redisTemplate.opsForSet().size(key);
        } catch (Exception e) {

            e.printStackTrace();
        } finally {
            RedisConnectionUtils.unbindConnection(Objects.requireNonNull(redisTemplate.getConnectionFactory()));
        }
        return 0;
    }

    /**
     * 检查当前set集合是否存在 o 值
     *
     * @return java.lang.Boolean
     * @Author zpc
     * @Date 10:57 2020/9/7
     * @Param [key, o]
     **/
    public Boolean checkSetEleIsExits(String key, Object o) {

        try {
            return redisTemplate.opsForSet().isMember(key, o);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            RedisConnectionUtils.unbindConnection(Objects.requireNonNull(redisTemplate.getConnectionFactory()));
        }
        return false;
    }

    /**
     * 获取set集合中所有元素
     *
     * @return java.lang.Boolean
     * @Author zpc
     * @Date 10:57 2020/9/7
     * @Param [key, o]
     **/
    public Set<Object> getSetAllEleBykey(String key) {

        try {
            return redisTemplate.opsForSet().members(key);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            RedisConnectionUtils.unbindConnection(Objects.requireNonNull(redisTemplate.getConnectionFactory()));
        }
        return new HashSet<>();
    }

    /**
     * 设置value值的分数
     *
     * @param key
     * @return void
     * @author zpc
     * @date 18:18 2021/9/7
     * @param: value
     * @param: score
     **/
    public void addZSetScore(String key, Object value, double score) {

        try {
            redisTemplate.opsForZSet().add(key, value, score);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            RedisConnectionUtils.unbindConnection(Objects.requireNonNull(redisTemplate.getConnectionFactory()));
        }

    }

    /**
     * 获取value值的排名
     *
     * @param key
     * @return void
     * @author zpc
     * @date 18:21 2021/9/7
     * @param: value
     **/
    public void getZSetScore(String key, Object value) {

        try {
            redisTemplate.opsForZSet().rank(key, value);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            RedisConnectionUtils.unbindConnection(Objects.requireNonNull(redisTemplate.getConnectionFactory()));
        }

    }

    // 删除某一个key
    public void del(String key) {
        try {
            redisTemplate.delete(key);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            RedisConnectionUtils.unbindConnection(Objects.requireNonNull(redisTemplate.getConnectionFactory()));
        }
    }

    // 删除多个key
    public void del(Set<String> keys) {
        try {

            redisTemplate.delete(keys);
        } catch (Exception e) {

            e.printStackTrace();
        }
    }

    /**
     * 获取分布式锁
     **/
    public boolean getLock(String lockkey, String value, int expireTime) {
        Boolean aBoolean = false;
        try {
            aBoolean = redisTemplate.opsForValue().setIfAbsent(lockkey, value, expireTime, TimeUnit.SECONDS);
            return aBoolean != null && aBoolean;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            RedisConnectionUtils.unbindConnection(Objects.requireNonNull(redisTemplate.getConnectionFactory()));
        }
        return aBoolean;
    }

    /**
     * 释放锁
     *
     * @param lockKey key名称
     */
    public void delLock(String lockKey) {
        redisTemplate.delete(lockKey);

    }

    //存入list
    public void leftPush(String key, Object msg) {

        redisTemplate.opsForList().leftPush(key, msg);
    }

    //存入list
    public void listPushAll(String key, List<JSONObject> arry, String direction) {
        if ("left".equals(direction)) {
            redisTemplate.opsForList().leftPushAll(key, arry.toArray());
        } else {
            redisTemplate.opsForList().rightPushAll(key, arry.toArray());
        }

    }

    //消费list
    public Object rightPop(String key) {

        return redisTemplate.opsForList().rightPop(key, 1, TimeUnit.SECONDS);
    }

    //消费list
    public void rightPush(String key, Object msg) {

        redisTemplate.opsForList().rightPush(key, msg);
    }

    //消费list
    public Long getQueueSize(String key) {

        return redisTemplate.opsForList().size(key);
    }

    //getAll
    public List<Object> getAll(String key) {
         List<Object> range = redisTemplate.opsForList().range(key, 0, -1);
        redisTemplate.delete(key);
        return range;
    }
}
